﻿using Abp;
using Abp.Application.Navigation;
using Abp.Collections.Extensions;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Runtime.Session;
using Microsoft.EntityFrameworkCore;
using Mt.Site.Core.ContentManagement.Values;
using Mt.Site.Core.CustomConfigurations;
using Mt.Site.Core.Navigations;
using Mt.Site.Core.Navigations.Entities;
using Mt.Site.Core.Navigations.Exceptions;
using Mt.Site.Core.Navigations.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mt.Site.Core.ContentManagement.Impl
{
    public class MenuContentHelper : IMenuContentHelper, ITransientDependency
    {
        private readonly ICustomConfigManager _customConfigManager;
        private readonly IRepository<Menu, Guid> _menuRepository;
        private readonly IRepository<BackEndModule, Guid> _backEndModuleRepository;
        private readonly INavigationManager _navigationManager;

        public IAbpSession AbpSession { get; set; }

        private readonly IMenuCache _menuCache;

        public MenuContentHelper(
            INavigationManager navigationManager,
            ICustomConfigManager customConfigManager,
            IMenuCache menuCache,
            IRepository<Menu, Guid> menuRepository,
            IRepository<BackEndModule, Guid> backEndModuleRepository)
        {
            _navigationManager = navigationManager;
            _customConfigManager = customConfigManager;
            _menuCache = menuCache;

            _menuRepository = menuRepository;
            _backEndModuleRepository = backEndModuleRepository;
        }

        public ICustomConfigManager CustomConfigManager => _customConfigManager;
        public async Task<ContentConfig> GetConfig(string customKey)
        {
            if (customKey.IsNullOrEmpty())
            {
                return null;
            }
            var config = await _customConfigManager.GetOtherCustomConfigurationAsync<ContentConfig>(customKey);
            config.KeyName = customKey;
            return config;
        }
        public async Task<ContentConfig> GetConfig(string customKey, long menuId)
        {
            customKey = await GetCustomKey(customKey, menuId);

            return await GetConfig(customKey);
        }

        public async Task<string> GetCustomKey(string customKey, long menuId)
        {
            //if (customKey.IsNullOrEmpty())
            //{
            //    //从栏目自定义配置中获取
            //    var entity = await _menuInfoManager.GetConfig(menuId, MenuInfoManager.CustomedConfig);
            //    customKey = entity?.ExtensionData;
            //}
            if (customKey.IsNullOrEmpty())
            {
                customKey = await GetModuleCustomData(menuId);
            }
            return customKey;
        }


        public async Task<List<string>> GetMenuPathAsync(MenuIdTraceCacheItem item)
        {
            var menuCache = await _navigationManager.GetContentMenuCacheAsync(AbpSession.GetTenantId());
            var items = menuCache.Items;
            var idTrace = item.IdTrace;

            List<string> list = new List<string>();

            for (int i = 0; i < idTrace.Count; i++)
            {
                var menuItem = _navigationManager.GetFrontendMenuItemDefinitionFromList(items, idTrace[i]);

                if (menuItem == null)
                {
                    throw new MenuItemNotFoundException(idTrace[i], AbpSession.GetTenantId());
                }

                if (i == idTrace.Count - 1)
                {
                    list.Add(item.GetDisplayName(menuItem));
                }
                else
                {
                    list.Add(item.GetDisplayName(menuItem));
                    items = menuItem.Items;
                }
            }

            return list;
        }

        public async Task<string> GetModuleCustomData(long menuId)
        {
            var query = from menu in _menuRepository.GetAll()
                        join backendmodule in _backEndModuleRepository.GetAll()
                        on menu.BackEndModuleId equals backendmodule.Id
                        where menu.IsActive == true && menu.DisplayType != MenuDisplayType.Frontend && menu.AuxiliaryId == menuId
                        select backendmodule.CustomData;

            return await query.FirstOrDefaultAsync();
        }

        public async Task<List<MenuSampeInfo>> GetAllMenusByCustomKeyAsync(string customKey, string moduleName)
        {
            // 1. 在module表中找所有同key值的module, 找出所有这些module的栏目，过滤栏目树找出是叶子节点的（顺便找出他们的叶子）
            var query = from menu in _menuRepository.GetAll()
                        join backendmodule in _backEndModuleRepository.GetAll()
                        on menu.BackEndModuleId equals backendmodule.Id
                        where menu.IsActive == true && menu.DisplayType != MenuDisplayType.Frontend
                            && backendmodule.CustomData == customKey && backendmodule.Name == moduleName
                        orderby menu.Code
                        select new { menu.AuxiliaryId, menu.Id };

            var menuIds = await query.ToListAsync();

            var result = new List<MenuSampeInfo>();

            var menuCache = await _navigationManager.GetContentMenuCacheAsync(AbpSession.GetTenantId());
            List<string> list = new List<string>();


            foreach (var item in menuIds)
            {
                var items = menuCache.Items;

                var itemIdTrace = await _menuCache.GetMenuIdTraceCacheItemAsync(item.AuxiliaryId);
                var idTrace = itemIdTrace.IdTrace;
                list.Clear();

                // 遍历栏目树，查找栏目的路径
                for (int i = 0; i < idTrace.Count; i++)
                {
                    var menuItem = _navigationManager.GetFrontendMenuItemDefinitionFromList(items, idTrace[i]);

                    if (menuItem == null)
                    {
                        throw new MenuItemNotFoundException(idTrace[i], AbpSession.GetTenantId());
                    }

                    if (i == idTrace.Count - 1)
                    {
                        if (menuItem.IsLeaf ||
                            menuItem.Items.Where(t =>
                            {
                                var customData = t.CustomData.As<ContentMenuItemCustomData>();
                                if (customData.DisplayType == MenuDisplayType.Backend || customData.DisplayType == MenuDisplayType.Common)
                                {
                                    return true;
                                }
                                return false;
                            }).Count() == 0)
                        {
                            list.Add(itemIdTrace.GetDisplayName(menuItem));
                        }
                        else
                        {
                           list.Clear();
                        }
                    }
                    else
                    {
                        list.Add(itemIdTrace.GetDisplayName(menuItem));
                        items = menuItem.Items;
                    }
                }

                if(list.Count > 0)
                {
                    result.Add(new MenuSampeInfo 
                    { 
                        Path = list.JoinAsString(" / "),
                        AuxiliaryId =item.AuxiliaryId ,
                        Id = item.Id,
                        CustomKey = customKey
                    });
                }
            }

            return result;
        }
    }
}
